#include "KmyIFile.h"

KmyIFile::KmyIFile()
{

}

KmyIFile::KmyIFile(const string &root_path)
    : rootpath(root_path)
{
//    this->rootpath = root_path;
}

KmyIFile::~KmyIFile(){

}

/* KmyImagePak读取 */
KmyImagePak* KmyIFile::readImagePak(ResPathImage *rpi){
    int num;
    int colormode;
    int file_type;
    St_Rect* ranges = NULL;
    if (!rpi->res_clip.empty()){
        fileOpen(rpi->res_clip);
        int size = getFileSize(rpi->res_clip);
        u8 *clip = new u8[size];
        read(rpi->res_clip, (void*)clip, size);
        fileClose(rpi->res_clip);
        int *p = (int*)clip;
        num = *p;
        p++;
        ranges = new St_Rect[num];
        for (int i=0; i<num; i++){
            ranges[i].x = *p++;
            ranges[i].y = *p++;
            ranges[i].w = *p++;
            ranges[i].h = *p++;
        }
        colormode = *p;
        delete[] clip;
        file_type = 0;  //二进制
    }else{
        num = 1;
        colormode = 1;
        file_type = 1;   //png
    }
    if (file_type == 0){
        fileOpen(rpi->res_image);
        int imagesize = getFileSize(rpi->res_image);
        u8* imgbin = new u8[imagesize];
        read(rpi->res_image, (void*)imgbin, imagesize);
        int *p = (int*)imgbin;
        colormode = *p++;
        int width = *p++;
        int height = *p++;
        switch (colormode){
        case 0: // RGBA8
        {
            KmyITexture *tex = new KmyITexture(
                        KmyITexture::TEXTURE_MODE_RGBA8, (const u8*)p,
                        width, height, false);
            KmyImagePak *imgp = new KmyImagePak(tex, num, ranges);
            delete[] imgbin;
            return imgp;
        }break;
        case 1: // RGBA4
        {
            KmyITexture *tex = new KmyITexture(
                        KmyITexture::TEXTURE_MODE_RGBA4, (const u8*)p,
                        width, height, false);
            KmyImagePak *imgp = new KmyImagePak(tex, num, ranges);
            delete[] imgbin;
            return imgp;
        }break;
        case 2:     // RBG565
        {
            int nsize = width*height*4;
            u8* imgnbin = new u8[nsize];
            u32 *p4=(u32*)imgnbin;
            u16 *p2=(u16*)p;
            for (int i=0; i<width*height; i++){
                u32 b= (*p2&(31<<11))>>8;
                u32 g= (*p2&(63<<5))<<5;
                u32 r= (*p2&31)<<19;
                u32 a= 0xff000000;
                *p4=b|g|r|a;
                p2++;
                p4++;
            }
            KmyITexture *tex = new KmyITexture(
                        KmyITexture::TEXTURE_MODE_ARGB8, (const u8*)imgnbin,
                        width, height, false);
            KmyImagePak *imgp = new KmyImagePak(tex, num, ranges);
            delete[] imgbin;
            delete[] imgnbin;
            return imgp;
        }break;
        case 3:     //ARGB8
        {
            KmyITexture *tex = new KmyITexture(
                        KmyITexture::TEXTURE_MODE_ARGB8, (const u8*)p,
                        width, height, false);
            KmyImagePak *imgp = new KmyImagePak(tex, num, ranges);
            delete[] imgbin;
            return imgp;
        }break;
        case 4:     // RGB8
        {
            int nsize = width*height*4;
            u8* imgnbin = new u8[nsize];
            u8 *p3=(u8*)p;
            u32 *p4=(u32*)imgnbin;
            for (int i=0; i<width*height; i++){
                u8 b=*p3++;
                u8 g=*p3++;
                u8 r=*p3++;
                *p4=b|(g<<8)|(r<<16)|(0xff<<24);
                p4++;
            }
            KmyITexture *tex = new KmyITexture(
                        KmyITexture::TEXTURE_MODE_ARGB8, (const u8*)imgnbin,
                        width, height, false);
            KmyImagePak *imgp = new KmyImagePak(tex, num, ranges);
            delete[] imgbin;
            delete[] imgnbin;
            return imgp;
        }break;
        case 5:     // ARGB4
        {
            int nsize = width*height*4;
            u8* imgnbin = new u8[nsize];
            u32 *p4=(u32*)imgnbin;
            u16 *p2=(u16*)p;
            for (int i=0; i<width*height; i++){
                u32 b= *p2 & 0x000f <<4;
                u32 g= *p2 & 0x00f0 <<12;
                u32 r= *p2 & 0x0f00 <<20;
                u32 a= *p2 & 0xf000 <<28;
                *p4=b|g|r|a;
                p2++;
                p4++;
            }
            KmyITexture *tex = new KmyITexture(
                        KmyITexture::TEXTURE_MODE_ARGB8, (const u8*)imgnbin,
                        width, height, false);
            KmyImagePak *imgp = new KmyImagePak(tex, num, ranges);
            delete[] imgbin;
            delete[] imgnbin;
            return imgp;
        }break;
        }
    }
    return NULL;
}

/** 读取脚本 */
KmyScript* KmyIFile::readScript(ResPathScript *rps){
    if (rps->res_head.empty()){
        return NULL;
    }
    fileOpen(rps->res_head);
    int size = getFileSize(rps->res_head);
    u8 *buff = new u8[size];
    read(rps->res_head, (void*)buff, size);
    fileClose(rps->res_head);
    KmyStream stm_head(buff, size);

    fileOpen(rps->res_body);
    size = getFileSize(rps->res_body);
    buff = new u8[size];
    read(rps->res_body, (void*)buff, size);
    fileClose(rps->res_body);
    KmyStream stm_body(buff, size);

    fileOpen(rps->res_text);
    size = getFileSize(rps->res_text);
    buff = new u8[size];
    read(rps->res_text, (void*)buff, size);
    fileClose(rps->res_text);
    KmyStream stm_text(buff, size);

    KmyScript *ksp = new KmyScript(rps->res_name,
                                   &stm_head, &stm_body, &stm_text);

    stm_head.finalize();
    stm_body.finalize();
    stm_text.finalize();
    return ksp;
}

/** 读取精灵数据（不自动读图，读图需手动 */
KmySpriteTemplate *KmyIFile::readSprite(ResPathSprite *rps){
    if (rps->res_sprdata.empty()){
        return NULL;
    }
    fileOpen(rps->res_sprdata);
    int size = getFileSize(rps->res_sprdata);

    u8* buff = new u8[size];
    read(rps->res_sprdata, (void*)buff, size);
    fileClose(rps->res_sprdata);

    KmySpriteTemplate *spt = new KmySpriteTemplate;
//    int offset;
//    u8 *p = buff;
    KmyStream stm(buff, size);
    int namesize = stm.getInt();
    St_Buff* sbuff = stm.readBuff(namesize);
    spt->spritename = string((char*)sbuff->buff);
    delete sbuff;
    namesize = stm.getInt();
    sbuff = stm.readBuff(namesize);
    spt->imagepakname = string((char*)sbuff->buff);
    delete sbuff;

    //---------------image part----------------------
    spt->imagepart_num = stm.getInt();
    spt->image_parts = new ST_imagePart[spt->imagepart_num];
    for (int i=0; i<spt->imagepart_num; i++){
        spt->image_parts[i].image_index = stm.getInt();
        spt->image_parts[i].x = stm.getInt();
        spt->image_parts[i].y = stm.getInt();
        spt->image_parts[i].trans = stm.getInt();
        spt->image_parts[i].alpha = stm.getFloat();
        spt->image_parts[i].rotate = stm.getFloat();
        spt->image_parts[i].scale_x = stm.getInt();
        spt->image_parts[i].scale_y = stm.getInt();
    }
    //---------------------cd part--------------------------------
    spt->cdpart_num = stm.getInt();
    spt->cd_parts = new ST_cdPart[spt->cdpart_num];
    for (int i=0; i<spt->cdpart_num; i++){
        spt->cd_parts[i].mask = stm.getInt();
        spt->cd_parts[i].x1 = stm.getInt();
        spt->cd_parts[i].y1 = stm.getInt();
        spt->cd_parts[i].x2 = stm.getInt();
        spt->cd_parts[i].y2 = stm.getInt();
    }
    //-------------------image frame-------------------------------
    spt->image_frame_num = stm.getInt();
    spt->ifs = new ST_indexs[spt->image_frame_num];
    for (int i=0; i<spt->image_frame_num; i++){
        spt->ifs[i].num = stm.getInt();
        spt->ifs[i].indexs = new int[spt->ifs[i].num];
        for (int j=0; j<spt->ifs[i].num; j++){
            spt->ifs[i].indexs[j] = stm.getInt();
        }
    }
    //-----------------cd frame--------------------------------------
    spt->cd_frame_num = stm.getInt();
    spt->cfs = new ST_indexs[spt->cd_frame_num];
    for (int i=0; i<spt->cd_frame_num; i++){
        spt->cfs[i].num = stm.getInt();
        spt->cfs[i].indexs = new int[spt->cfs[i].num];
        for (int j=0; j<spt->cfs[i].num; j++){
            spt->cfs[i].indexs[j] = stm.getInt();
        }
    }
    //------------------anime--------------------------------------
    spt->anime_num = stm.getInt();
    spt->animes = new ST_anime[spt->anime_num];
    for (int i=0; i<spt->anime_num; i++){
        namesize = stm.getInt();
        sbuff = stm.readBuff(namesize);
        spt->animes[i].name = string((char*)sbuff->buff);
        spt->animes[i].frame_num = stm.getInt();
        spt->animes[i].image_frame_indexs = new int[spt->animes[i].frame_num];
        spt->animes[i].cd_frame_indexs = new int[spt->animes[i].frame_num];
        for (int j=0; j<spt->animes[i].frame_num; j++){
            spt->animes[i].image_frame_indexs[j]= stm.getInt();
        }
        for (int j=0; j<spt->animes[i].frame_num; j++){
            spt->animes[i].cd_frame_indexs[j]= stm.getInt();
        }
    }

    // new maxrange
    spt->max_range.x = stm.getInt();
    spt->max_range.y = stm.getInt();
    spt->max_range.w = stm.getInt();
    spt->max_range.h = stm.getInt();

    delete[] buff;
    spt->imagepak = NULL;
//    spt->imagepak = KmyResourceManager::getInstance()->getImage(spt->imagepakname);
    return spt;
}

KmyFont* KmyIFile::readFont(ResPathFont *rpf){
    if (rpf->res_ascii_font.empty()){ // 必须有ascii字库
        return NULL;
    }
    KmyFont *font = new KmyFont();
//    vector<u8*> datas;
    fileOpen(rpf->res_ascii_range);
    int size = getFileSize(rpf->res_ascii_range);
    u8* buff = new u8[size];
    read(rpf->res_ascii_range, (void*)buff, size);
    fileClose(rpf->res_ascii_range);
    KmyStream stm(buff, size);
    int mode = stm.getInt();
//    font->bit_per_point = (mode&0xff00)>>8;

    if (mode & 2){
        font->is_with_width = true;
    }else{
        font->is_with_width = false;
    }
    if (mode & 1){
        font->is_mapping_table = true;
    }else{
        font->is_mapping_table = false;
    }
    int range_number = stm.getInt();
    font->ascii_width = stm.getInt();
    font->ascii_height = stm.getInt();
    int start = stm.getInt();
    int count = stm.getInt();
    delete[] buff;
    fileOpen(rpf->res_ascii_font);
    size = getFileSize(rpf->res_ascii_font);
    u8* data0 = new u8[size];
    read(rpf->res_ascii_font, (void*)data0, size);
    fileClose(rpf->res_ascii_font);

    if (rpf->res_mbcs_range.empty()){
        // 没有双字节字符
        font->is_mapping_table = false;
        font->fullfont.range_count = 1;
        font->fullfont.data = new u8*[1];
        font->fullfont.start_code = new int[font->fullfont.range_count];
        font->fullfont.range = new int[font->fullfont.range_count];
        font->mbcs_width = 0;
        font->mbcs_height = 0;
        font->fullfont.start_code[0]=start;
        font->fullfont.range[0]=count;
        font->fullfont.data[0]=data0;
    }else{
        // 有双字节字符
        fileOpen(rpf->res_mbcs_range);
        size = getFileSize(rpf->res_mbcs_range);
        buff = new u8[size];
        read(rpf->res_mbcs_range, (void*)buff, size);
        fileClose(rpf->res_mbcs_range);
        stm.initialize(buff, size);
        mode = stm.getInt();
        fileOpen(rpf->res_mbcs_font);
//        size = getFileSize(rpf->res_mbcs_font);
//        u8 *datay = new u8[size];
//        read(rpf->res_mbcs_font, (void*)datay, size);
        if (font->is_mapping_table){
            // 使用字符映射表
            font->mapping_tab.data = new u8*[2];
            font->mapping_tab.data[0] = data0;
            size = getFileSize(rpf->res_mbcs_font);
            font->mapping_tab.data[1]=new u8[size];
            read(rpf->res_mbcs_font, (void*)font->mapping_tab.data[1], size);
            // 此处还差映射表的读取
        }else{
            // 不使用字符映射表
            range_number = stm.getInt();
            font->fullfont.range_count = range_number+1;
            font->fullfont.data = new u8*[range_number+1];
            font->fullfont.start_code = new int[font->fullfont.range_count];
            font->fullfont.range = new int[font->fullfont.range_count];
            font->mbcs_width = stm.getInt();
            font->mbcs_height = stm.getInt();
            font->fullfont.start_code[0]=start;
            font->fullfont.range[0]=count;
            font->fullfont.data[0]=data0;
            for (int i=1; i<font->fullfont.range_count; i++){
               font->fullfont.start_code[i]=stm.getInt();
               font->fullfont.range[i]=stm.getInt();
               int block_size = 0;
//               if (font->bit_per_point==1){
                   block_size = font->mbcs_width*font->mbcs_height*font->fullfont.range[i]>>3;
//               }else if (font->bit_per_point==2){
//                   block_size = font->mbcs_width*font->mbcs_height*font->fullfont.range[i]>>2;
//               }
               if (font->is_with_width){
                   block_size+=font->fullfont.range[i]*4;
               }

               u8 *datax =new u8[block_size];
               int readsize = read(rpf->res_mbcs_font, (void*)datax, block_size);
               font->fullfont.data[i]=datax;
               if (readsize!=block_size){
                   delete buff;
                   fileClose(rpf->res_mbcs_font);
                   return NULL;
               }
            }

        }
        delete[] buff;
        fileClose(rpf->res_mbcs_font);
    }
    return font;
}
